#include <rtthread.h>
#include <string.h>
#include "gb_15322_pal.h"
#include "uc_log.h"
rt_int16_t gb_15322_head(rt_uint8_t *in, rt_uint32_t inlen)
{
    for (int n = 0; n < inlen; n++)
    {
        if (in[n] == PRO_HEAD && in[n + 1] == GB18322_VERSION)
        {
            return n;
        }
    }

    return -1;
}

rt_int8_t gb_15322_get_version(rt_uint8_t *head)
{
    return head[GB18322_VERSION_OFFSET];
}

rt_int32_t gb_15322_get_addr(rt_uint8_t *head)
{
    return (rt_int32_t) * ((rt_int32_t *)&head[GB18322_ADDR_OFFSET]);
}

rt_int16_t gb_15322_get_len(rt_uint8_t *head)
{
    return (rt_int16_t)(*((rt_int16_t *)(head + GB18322_LEN_OFFSET)));
}

rt_int16_t gb_15322_tail(rt_uint8_t *in, rt_uint32_t inlen)
{
    for (int n = 0; n < inlen; n++)
    {
        if (in[n] == PRO_TAIL)
            return n;
    }

    return -1;
}

/**
 * @brief       crc计算
 * @param       crc:crc计算的初始数据，初始值为0x1234
 *              buff:待计算的数据
 *              data_len:待计算的数据长度
 * @return      计算得到的crc值
 * @par         创建
 */
static rt_uint8_t checksum(rt_uint8_t *buff, rt_uint32_t data_len)
{
    rt_uint32_t index = 0;
    rt_uint8_t sum = 0;

    for (index = 0; index < data_len; index++)
    {
        sum = sum + buff[index];
    }
    // TRACE_D("sum 0x%x", sum);

    return sum;
}

rt_int32_t gb_15322_checksum(rt_uint8_t *in, rt_uint32_t inlen)
{
    if (checksum(in, inlen - 1) == in[inlen - 1])
        return 0;
    else
    {
        TRACE_E("15322_checksum err");
        return 1;
    }
}

/**
 * @brief       gb_15322协议解析
 * @param
                in 数据输入
                inlen 输入数据长度
                out 数据输出,out->data 需指定存储空间
 * @return      0:成功；其它：-1标识头不正确,2校验和不正确,3标识尾不正确,4解析的数据长度与输入数据长度不符
 * @par         创建
 *              lcj2020-7-2创建
 */
rt_int32_t gb_15322_decode(rt_uint8_t *in, rt_uint32_t inlen, void *out)
{
    rt_uint16_t pos = 0;
    // rt_uint8_t checksum_cal = 0;
    s_gb_15322 *out_p = RT_NULL;

    out_p = (s_gb_15322 *)out;

    pos = 0;

    if ((in == NULL) || (inlen < 5) || in[0] != PRO_HEAD)
    {
        TRACE_E("gb_15322_decode error -1 inlen=%d,in[0]=%x", inlen, in[0]);
        return -1;
    }

    out_p->precode = in[pos];
    pos += 1;

    out_p->version = in[pos];
    pos += 1;

    out_p->addr = (unsigned int)*((unsigned int *)&in[pos]);
    pos += 4;

    out_p->ctl = in[pos];
    pos += 1;

    out_p->datalen = (unsigned short)*((unsigned short *)&in[pos]);
    pos += 2;

    if (out_p->datalen > 0)
    {
        // rt_memcpy(out_p->data, &in[pos], out_p->datalen);
        out_p->data = &in[pos];
        pos += out_p->datalen;
    }

    // checksum_cal = checksum(in, pos);

    // out_p->checksum = in[pos];
    pos += 1;
    out_p->tailcode = in[pos];

    // if (out_p->checksum != checksum_cal)
    //{
    //     TRACE_I("gb_15322 checksum err 0x%x != 0x%x", out_p->checksum, checksum_cal);
    //     return -2;
    // }

    if (PRO_TAIL != out_p->tailcode)
    {
        TRACE_E("gb_15322 tailcode err 0x%x", out_p->tailcode);
        return -3;
    }

    return 0; // 成功
}

/**
 * @brief       gb_15322协议组包
                in ucc格式数据输入
                out 数据流输出

 * @return      outlen 输出数据长度
 * @par         创建
 *              lcj2020-7-2创建
 */
int gb_15322_encode(void *in, char *out, int *outlen)
{
    rt_uint16_t pos = 0;

    s_gb_15322 *in_p = RT_NULL;

    in_p = (s_gb_15322 *)in;

    pos = 0;

    if (in_p == NULL)
    {
        TRACE_E("gb_15322_encode error -1");
        return -1;
    }

    out[pos] = PRO_HEAD;
    pos += 1;

    out[pos] = in_p->version;
    pos += 1;

    *((unsigned int *)&out[pos]) = in_p->addr;
    pos += 4;

    out[pos] = in_p->ctl;
    pos += 1;

    //(unsigned short)*((unsigned short*)&out[pos]) = (in_p->datalen);
    // out[pos] = (in_p->datalen >> 8);
    // out[pos + 1] = (in_p->datalen & 0xFF);
    out[pos] = (in_p->datalen & 0xFF);
    out[pos + 1] = (in_p->datalen >> 8);

    pos += 2;

    // rt_memcpy(&out[pos], in_p->data, in_p->datalen);
    for (int n = 0; n < in_p->datalen; n++)
    {
        out[pos + n] = *(in_p->data + n);
    }
    pos += in_p->datalen;

    out[pos] = checksum(out, pos);
    pos += 1;

    out[pos] = PRO_TAIL;
    pos += 1;

    *outlen = pos;

    return 0; // 成功
}

// gb_15322协议数据过滤,获取完整的数据帧

rt_int32_t gb_15322_fliter(rt_uint8_t *in, rt_uint32_t inlen)
{
    // rt_uint32_t pos = 0;
    rt_int32_t needlen = -1;
    rt_uint32_t datalen = 0;
    rt_uint32_t framelen = 0;

    // 判断协议头
    if ((in[0] != PRO_HEAD) || (inlen == 0))
    {
        TRACE_E("gb_15322_fliter error -1 inlen=%d,in[0]=%x", inlen, in[0]);

        return needlen;
    }

    // 获取数据帧长度
    if (inlen >= GB18322_LEN_OFFSET)
    {
        datalen = ((unsigned short)*((unsigned short *)&in[GB18322_LEN_OFFSET]));

        // 判断数据是否完整，包括前导字,命令字,数据长度,数据域,校验,后导字
        framelen = datalen + GB18322_LEN_OFFSET + 4;

        if (inlen >= framelen)
        {
            if (in[framelen - 1] == PRO_TAIL &&
                in[framelen - 2] == checksum(in, framelen - 2))
            {
                needlen = 0;
            }
            else
            {
                TRACE_E("gb_15322_fliter error -1 datalen=%d,framlen=%d,tail=%x,in[0]=%x", datalen, framelen, in[framelen - 1]);
                needlen = -1;
            }
        }
        else
        {
            needlen = framelen - inlen;

            TRACE_I("gb_15322_fliter inlen<framelen inlen=%d,framelen=%d,needlen=%d\n", inlen, framelen, needlen);
        }
    }
    else
    {
        needlen = GB18322_LEN_OFFSET - inlen;

        TRACE_E("gb_15322_fliter inlen<FRAME_LEN_POS inlen=%d,needlen=%d", inlen, needlen);
    }

    return needlen;
}
